package com.david.bluetooth.ble.musicctr

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.bluetooth.BluetoothGattService
import android.bluetooth.BluetoothProfile
import android.content.Intent
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import com.david.bluetooth.APP
import com.david.bluetooth.R
import com.david.bluetooth.ble.BleDevAdapter
import com.david.bluetooth.ble.BleServerActivity
import java.util.UUID

class BleClientMusicService: Service() {
    private val TAG = MusicBleClientActivity::class.java.simpleName

    private var mBluetoothGatt: BluetoothGatt? = null

    // 与服务端连接的Callback
    private var mBluetoothGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            val dev = gatt.device
            Log.i(TAG, String.format("onConnectionStateChange:%s,%s,%s,%s", dev.name, dev.address, status, newState))
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
                isConnected = true
                gatt.discoverServices() //启动服务发现


                logTv("device connect...:${dev.name}")

                //runOnUiThread {
                //    connectStatus?.text = "已连接"
                //}
                onTipsChangeListener?.onConnectChange(isConnected)
            } else {
                isConnected = false
                closeConn()

                logTv("device disconnect...:${dev.name}")

                onTipsChangeListener?.onConnectChange(isConnected)
                //runOnUiThread {
                //    connectStatus?.text = "未连接"
                //}
            }

            logTv(String.format(if (status == 0) (if (newState == 2) "与[%s]连接成功" else "与[%s]连接断开") else "与[%s]连接出错,错误码:$status", dev))
        }

        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
            Log.i(TAG, String.format("onServicesDiscovered:%s,%s,%s", gatt.device.name, gatt.device.address, status))
            if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功
                // 遍历获取BLE服务Services/Characteristics/Descriptors的全部UUID
                for (service in gatt.services) {
                    val allUUIDs = StringBuilder("""
    UUIDs={
    S=${service.uuid}
    """.trimIndent())
                    for (characteristic in service.characteristics) {
                        allUUIDs.append(",\nC=").append(characteristic.uuid)
                        for (descriptor in characteristic.descriptors) allUUIDs.append(",\nD=").append(descriptor.uuid)
                    }
                    allUUIDs.append("}")
                    Log.i(TAG, "onServicesDiscovered:$allUUIDs")
                    logTv("发现服务$allUUIDs")
                }
            }
        }

        override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
            val uuid = characteristic.uuid
            val valueStr = (characteristic.value)
            Log.i(TAG, String.format("onCharacteristicRead:%s,%s,%s,%s,%s", gatt.device.name, gatt.device.address, uuid, valueStr, status))
            logTv("读取Characteristic[$uuid]:\n$valueStr")
        }

        override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
            val uuid = characteristic.uuid
            val valueStr = String(characteristic.value)
            Log.i(TAG, String.format("onCharacteristicWrite:%s,%s,%s,%s,%s", gatt.device.name, gatt.device.address, uuid, valueStr, status))
            logTv("写入Characteristic[$uuid]:\n$valueStr")

            if(status == BluetoothGatt.GATT_SUCCESS){
                //写入成功
                Log.w(TAG,"写入成功：value:${characteristic.value} ;valueStr$valueStr");

            }else if(status == BluetoothGatt.GATT_FAILURE){
                //写入失败
                Log.e(TAG,"写入失败：" + valueStr);
            }else if(status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED){
                //没有权限
                Log.e(TAG,"没有权限！")
            }

            //在中心设备上在发现A特征值时要设置：bluetoothGatt.setCharacteristicNotification(A,,true);表示该特征值可以接收通知；
            gatt.setCharacteristicNotification(characteristic, true)//设置此方法才能收到onCharacteristicChanged的通知
        }

        // 特征值改变时的处理逻辑
        override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
            val uuid = characteristic.uuid
            // 处理接收到的数据

            val valueStr = String(characteristic.value)
            Log.i(TAG, String.format("onCharacteristicChanged:%s,%s,%s,%s", gatt.device.name, gatt.device.address, uuid, valueStr))
            logTv("通知Characteristic[$uuid]:\n$valueStr")
        }

        override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
            val uuid = descriptor.uuid
            val valueStr = String(descriptor.value)
            Log.i(TAG, String.format("onDescriptorRead:%s,%s,%s,%s,%s", gatt.device.name, gatt.device.address, uuid, valueStr, status))
            logTv("读取Descriptor[$uuid]:\n$valueStr")
        }

        override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
            val uuid = descriptor.uuid
            val valueStr = String(descriptor.value)
            Log.i(TAG, String.format("onDescriptorWrite:%s,%s,%s,%s,%s", gatt.device.name, gatt.device.address, uuid, valueStr, status))
            logTv("写入Descriptor[$uuid]:\n$valueStr")
        }
    }

    override fun onCreate() {
        super.onCreate()
        mBleDevAdapter = BleDevAdapter(BleDevAdapter.Listener { dev ->
            closeConn()
            mBluetoothGatt = dev.connectGatt(this@BleClientMusicService, false, mBluetoothGattCallback) // 连接蓝牙设备
            logTv(String.format("与[%s]开始连接............", dev))
        })
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when(val cmdKey = intent?.getByteExtra(BLE_MUSIC_CLIENT_CMD_KEY, -1)) {
            BLE_MUSIC_CLIENT_ACTION_CMD_SCAN -> {
                reScan()
            }
            BLE_MUSIC_CLIENT_ACTION_CMD_CONNECT -> {
                if (!isConnected) {
                    connect()
                }
            }
            BLE_MUSIC_CLIENT_ACTION_CMD_DISCONNECT -> {
                closeConn()
            }
            else -> {
                write(cmdKey?:-1, intent?.getByteExtra(BLE_MUSIC_CLIENT_CMD_ACTION_KEY, -1)?: -1)
            }
        }

        startNotification()
        return START_STICKY
    }

    // BLE中心设备连接外围设备的数量有限(大概2~7个)，在建立新连接之前必须释放旧连接资源，否则容易出现连接错误133
    private fun closeConn() {
        if (mBluetoothGatt != null) {
            mBluetoothGatt!!.disconnect()
            mBluetoothGatt!!.close()
        }

        logTv("connect closed...")
    }

    // 注意：连续频繁读写数据容易失败，读写操作间隔最好200ms以上，或等待上次回调完成后再进行下次读写操作！
    // 写入数据成功会回调->onCharacteristicWrite()
    //最大包大小为18byte，多于18个会分包
    private fun write(actionType: Byte, action: Byte, actionValue: Byte? = null) {
        val service: BluetoothGattService? = getGattService(BleServerActivity.UUID_SERVICE)
        if (service != null) {
            //val text: String = "123"
            val characteristic = service.getCharacteristic(BleServerActivity.UUID_CHAR_WRITE) //通过UUID获取可写的Characteristic
            if (actionValue == null) {
                characteristic.value = byteArrayOf(actionType, action, (actionType + action).toByte()) //text.toByteArray() //单次最多20个字节
            } else {
                characteristic.value = byteArrayOf(actionType, action, actionValue, (actionType + action + actionValue).toByte()) //text.toByteArray() //单次最多20个字节
            }
            mBluetoothGatt!!.writeCharacteristic(characteristic)
        }
    }

    // 获取Gatt服务
    private fun getGattService(uuid: UUID): BluetoothGattService? {
        if (!isConnected) {
            APP.toast("没有连接", 0)
            return null
        }
        val service = mBluetoothGatt!!.getService(uuid)
        if (service == null) APP.toast("没有找到服务UUID=$uuid", 0)
        return service
    }

    fun logTv(msg: String?){
        tips.append(msg).append("\n").append("\n")
        Log.e(TAG, msg.toString())

        onTipsChangeListener?.onTipsChange(tips.toString())
    }

    fun reScan() {
        if (mBleDevAdapter!!.isScanning)
            APP.toast("正在扫描...", 0)
        else {
            mBleDevAdapter!!.reScan()
            logTv("start scan...")
        }
    }

    private fun connect() {
        closeConn()
        mBluetoothGatt = dev?.connectGatt(this@BleClientMusicService, false, mBluetoothGattCallback) // 连接蓝牙设备
        logTv(String.format("与[%s]开始连接............", dev))
    }


    /**
     * 启动一个前台通知，但通知栏会显示一个通知栏
     */
    private fun startNotification() {
        val builder: NotificationCompat.Builder = NotificationCompat.Builder(this, "server")
        builder.setContentTitle("musicBleClient")
        builder.setContentText("musicBleClient running...")
        builder.setSmallIcon(R.mipmap.ic_logo)
        builder.setContentIntent(PendingIntent.getActivity(this, 0, Intent(this, MusicServerActivity::class.java), PendingIntent.FLAG_IMMUTABLE))

        val silentChannel = NotificationChannel(
            "client",
            "musicBleClient",
            NotificationManager.IMPORTANCE_HIGH
        )
        silentChannel.name = "ble client is running..."
        silentChannel.setSound(null, null)
        silentChannel.enableVibration(false)
        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannel(silentChannel)

        // 这里两个通知使用同一个id且必须按照这个顺序后调用startForeground
        val id = 2
        //                        NotificationManagerCompat.from(this).notify(id, builder.build());
        startForeground(id, builder.build())
    }

    companion object{
        const val BLE_MUSIC_CLIENT_CMD_KEY = "BLE_MUSIC_ACTION_KEY"
        const val BLE_MUSIC_CLIENT_CMD_ACTION_KEY = "BLE_MUSIC_ACTION_DATA_KEY"
        const val BLE_MUSIC_CLIENT_CMD_ACTION_DATA_KEY = "BLE_MUSIC_ACTION_DATA_KEY"

        const val BLE_MUSIC_CLIENT_ACTION_CMD_SCAN:Byte = 125
        const val BLE_MUSIC_CLIENT_ACTION_CMD_CONNECT:Byte = 126
        const val BLE_MUSIC_CLIENT_ACTION_CMD_DISCONNECT:Byte = 127

        var scanDevices: ArrayList<BluetoothDevice> = ArrayList()

        //要连接的设备
        var dev: BluetoothDevice? = null

        var mBleDevAdapter: BleDevAdapter? = null

        var tips = StringBuilder()

        var isConnected = false

        var onTipsChangeListener: OnTipsChangeListener? = null
    }
}